<template>
  <div class="wft-online-edit" :class="{ 'light': mode == 'light' }">
    <div class="edit-title">
      <div>
        <h3>在线编辑器</h3>
        <el-upload class="wft-margin-left-20" action="#" :limit="1" accept=".json, .txt" :show-file-list="false" :before-upload="beforeUpload">
          <el-button :icon="FolderAdd">导入(json / txt)</el-button>
        </el-upload>
        <el-button @click="updatePanelJson()" class="wft-margin-left-20" :icon="Select">保存</el-button>
      </div>
      <div>
        <!-- 主题切换 -->
        <div @click="modeChange" :class="['mode-change', { 'tool-dark': mode == 'dark', 'tool-light': mode == 'light' }]">
          <img v-show="mode == 'dark'" src="@/assets/images/toolbar/dark.png">
          <img v-show="mode == 'light'" src="@/assets/images/toolbar/light.png">
        </div>
      </div>
    </div>
    <div class="edit-container">
      <MonacoEditor ref="MonacoEditRef" v-model="editJson" language="json" />
    </div>
  </div>
</template>
<script setup lang="ts">
import { ref, computed, onMounted, defineAsyncComponent, onUnmounted } from 'vue'
import { FolderAdd, Select } from '@element-plus/icons-vue'
import type { UploadRawFile } from 'element-plus'
import { useMessage, useMessageBox } from '@/hooks'
import useCommonStore from '@/store/common'
import { MonacoEditEnum, PanelJsonKeysEnum, KeyEventEnum } from '@/enums'
import localforageCache from '@/utils/localforage'
import { JSONParse, JSONStringify } from 'wft-utils'

const MonacoEditor = defineAsyncComponent(() => import('@/components/MonacoEditor/index.vue'))

let editJson = ref('')

onMounted(async () => {
  let curPanelJson = await localforageCache.get(PanelJsonKeysEnum.CUR_PREVIEW_PANEL_JSON_KEY) as string
  editJson.value = JSONStringify(curPanelJson)
  window.addEventListener(KeyEventEnum.ON_KEY_DOWN, onkeyDownHandler)
})

onUnmounted(() => {
  window.removeEventListener(KeyEventEnum.ON_KEY_DOWN, onkeyDownHandler)
})

// 导入json
const beforeUpload = (rawFile: UploadRawFile) => {
  const { name } = rawFile
  if(name.indexOf('.json') < 0 && name.indexOf('.txt') < 0) {
    return useMessage().error('请选择json文件或txt文件进行导入!')
  }
  const fr = new FileReader()
  fr.readAsText(rawFile)
  fr.onload = () => {
    try {
      let data = JSONParse(fr.result as string)
      editJson.value = JSONStringify(data)
      useMessage().success('导入成功')
    } catch(e) {
      useMessage().error('文件解析错误，请确保为json文件且格式数据正确!')
    }
  }
  return false
}

// 更新页面
const updatePanelJson = () => {
  useMessageBox().confirm('是否覆盖源试图内容？此操作不可逆！').then(async () => {
    try {
      const detail = JSONParse(editJson.value)
      window.opener.dispatchEvent(new CustomEvent(MonacoEditEnum.EDIT_PANEL_JSON, { detail }))
      await localforageCache.set(PanelJsonKeysEnum.CUR_PREVIEW_PANEL_JSON_KEY, detail)
      useMessage().success('视图已更新~')
    } catch(e) {
      useMessage().error('数据格式有误！')
    }
  })
}

// 监听 Ctrl + s
function onkeyDownHandler(event: KeyboardEvent) {
  if(event.ctrlKey && event.key == 's') {
    event.preventDefault()
    updatePanelJson()
  }
}

let mode = computed({
  get() {
    return useCommonStore().mode
  },
  set(mode) {
    useCommonStore().updatemode(mode)
  }
})

const MonacoEditRef = ref<InstanceType<typeof MonacoEditor>>()

const modeChange = () => {
  let theme = ''
  if(mode.value == 'dark') {
    mode.value = 'light'
    theme = 'vs'
  } else {
    mode.value = 'dark'
    theme = 'vs-dark'
  }
  MonacoEditRef.value!.updateOptions({ theme })
}
</script>
<style scoped>
.wft-online-edit {
  width: 100vw;
  height: 100vh;
}
</style>